'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ConCoder.bas Version 1.0
' A program to create subroutines that handle the values held in
' a configuration file.
'
' James Deakins, March 2013
'
' Config files hold pairs of values separated by an equal sign
' e.g. LastFileOpened=Example.bas
' the first value is a meaningful tag explaining what the 
' configuration item is, and the second value is the value
' that is to be assigned to the configuration item by the program.
' Note that there is no $ after the tag, and no quotes around
' the value.
' The value could be something like FALSE which is not a standard
' keyword in MMBasic.
' Therefore, we need custom code to read in the config values and
' allocate the values to global variables, and we need more custom 
' code to convert the global values back to entries in the config file.
' 
' Hand coding these functions is time consuming, and it is easy
' to mistype variable names etc. The user follows a few
' simple rules that can easily be put into code - so I did.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Input is a populated config file.
' Output is a text file containing the two functions.
'
' Cut-and-paste the two functions into the program that uses the
' config files, probably config.bas or a customised copy you have made.
'
' You will need a customise a copy of config.bas for every program that calls it.
'
' Assuming you haven't modified the names, the two functions
' will be called AllocateValues and WriteValues.  They will be called
' by ReadConfigFile and WriteConfigFile in Config.bas (or derivative).
' I assume you will either Chain to config.bas, or incorporate 
' the code into your program.  Whichever way you decide to go, replace the 
' functions at the end of config.bas with the functions created by this
' code.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
False = 0: True = NOT False

DQ$ = Chr$(34) ' saves a lot of typing.

defaultInFile$  = "renum.cfg" ' replace with your favourites - or make a config file and save the last one used :)
defaultOutFile$ = "renum.txt"

Input "What is the name of the config file";InFile$
Input "What do you want to call the output file";OutFile$

if InFile$ = "" then
  InFile$ = defaultInFile$
endif

if OutFile$ = "" then
  OutFile$ = defaultOutFile$
endif

Outfile1$ = "renum.tmp" ' this one will get deleted once its contents are copied to the end of OutFile$

PRINT "Reading from ";Infile$; " and writing to ";OutFile$

Open InFile$  for input   as #1
Open Outfile$ for output  as #2
Open Outfile1$ for output as #3 

PRINT #2, "'"
PRINT #2, "''''''''''''''''''''''''''''''''''''''''''''''''''''''''''"
PRINT #2, "' Function AllocateValues"
PRINT #2, "' Allocates values to global variables depending on the"
PRINT #2, "' values of param$ and value$ passed in."
PRINT #2, "' Returns a False if a param cannot be found in the IF 
PRINT #2, "' statements."
PRINT #2, "''''''''''''''''''''''''''''''''''''''''''''''''''''''''''"
PRINT #2, "'"
PRINT #2, "FUNCTION AllocateValues(Param$, Value$)"
PRINT #2
PRINT #2, "LOCAL UCParam$, bOK"
PRINT #2
PRINT #2, "bOK = True"
PRINT #2
PRINT #2, "UCParam$ = UCASE$(Param$)"
PRINT #2
PRINT #2, "' Use an IF statement to process each possible parameter."
PRINT #2

PRINT #3, "'"
PRINT #3, "'''''''''''''''''''''''''''''''''''''''''''''''''''"
PRINT #3, "' Function WriteValues"
PRINT #3, "' Read values of Global Variables and store then in"
PRINT #3, "' a configuration file."
PRINT #3, "' Returns a False if a param cannot be found in the 
PRINT #3, "' IF statements."
PRINT #3, "'''''''''''''''''''''''''''''''''''''''''''''''''''"
PRINT #3, "FUNCTION WriteValues(Param$, Value$)"
PRINT #3, "' Value$ is only used when displaying an error."
PRINT #3
PRINT #3, "LOCAL UCParam$, bOK, Out$"
PRINT #3
PRINT #3, "bOK = True"
PRINT #3
PRINT #3, "UCParam$ = UCASE$(Param$)"
PRINT #3

bFirstTime = True
DO WHILE NOT EOF(#1)
  Line Input #1, LineIn$
  if Left$(LineIn$,1) <> "'" then
    ptr = INSTR(1, LineIn$, "=")
    Param$ = LEFT$(LineIn$,ptr-1)
    IF ptr = LEN(LineIn$) THEN 
      Value$ = ""                 ' an empty value field
    ELSE
      Value$ = MID$( LineIn$,ptr+1)
    ENDIF
    UCParam$ = UCASE$(Param$)
    if bFirstTime then
      PRINT #2, "IF UCParam$ = " + DQ$ + UCParam$ + DQ$ + " THEN"
      PRINT #3, "IF UCParam$ = " + DQ$ + UCParam$ + DQ$ + " THEN"
      bFirstTime = False
    else
      PRINT #2, "ELSEIF UCParam$ = " + DQ$ + UCParam$ + DQ$ + " THEN"
      PRINT #3, "ELSEIF UCParam$ = " + DQ$ + UCParam$ + DQ$ + " THEN"
    endif    
    PRINT
    PRINT "Parameter name is "; Param$
    Input "Is the global variable it will be mapped to Numeric (N), String (S), Boolean (B) or Other (O) "; Type$
    Type$ = UCASE$(Type$)
    Input "Does the global variable it will be mapped to use exactly the same name as this parameter (Y/N) ";In$
    In$ = UCASE$(In$)
    If In$ = "Y" then
      VarName$ = Param$
    else
      if Type$ = "S" then
        Input "Do you want to just add a $ to the end of it "; In$
        In$ = UCASE$(In$)
        if In$ = "Y" then
          VarName$ = Param$ + "$"
        else
          Input "Please enter the exact name of the global variable "; VarName$
        endif
      else
        Input "Please enter the exact name of the global variable "; VarName$
      endif
    endif
    
    ' note: we use VarName$ for the program variable name and Param$ for the config file tag
    
    if Type$ = "N" then
      PRINT #2, "  " + VarName$ + " = VAL(Value$)"
      PRINT #3, "  " + "Out$ = " +  DQ$ + Param$ + "=" + DQ$ + " + STR$(" + VarName$ + ")"
      
    elseif Type$ = "S" then
      PRINT #2, "  " + VarName$ + " = Value$"
      PRINT #3, "  " + "Out$ = " + DQ$ + Param$ + "=" + DQ$ + " + " + VarName$
      
    elseif Type$ = "B" then
      PRINT #2, "  " + VarName$ + " = (UCASE$(Value$) = " + DQ$ + "TRUE" + DQ$ + ")" 
      PRINT #3, "  " +  "Out$ = " + DQ$ + Param$ + "=" + DQ$
      PRINT #3, "  " + "IF " + VarName$ + " THEN"  'testing value of program variable
      PRINT #3, "  " + "  Out$ = Out$ + " + DQ$ + "TRUE" + DQ$
      PRINT #3, "  " + "ELSE"
      PRINT #3, "  " + "  Out$ = Out$ + " + DQ$ + "FALSE" + DQ$
      PRINT #3, "  " + "ENDIF"
      
    elseif Type$ = "O" then
      PRINT #2, "  " + "' insert your own code here for variable " + VarName$
      PRINT #2, "'Will not run reliably unless you insert the code in AllocateValues!"
      PRINT #2, "END"
      PRINT #2
      PRINT #3, "  " + "' insert your own code here for variable " + VarName$
      PRINT #3, "'Will not run reliably unless you insert the code in WriteValues!"
      PRINT #3, "END"
      PRINT #3
      PRINT " Please remember to insert your own code in the functions for this variable."
    endif 
  endif  
LOOP

' Now insert the final bits of code for each of the functions
PRINT #2, "ELSE"
PRINT #2, "  PRINT " + DQ$ + "Unknown parameter and its value " + DQ$ + "; Param$; " + DQ$ + "=" + DQ$ + "; Value$"
PRINT #2, "  bOK = False"
PRINT #2, "ENDIF"
PRINT #2
PRINT #2, "AllocateValues = bOK"
PRINT #2
PRINT #2, "END FUNCTION ' AllocateValues "
PRINT #2
PRINT #2

PRINT #3, "ELSE"
PRINT #3, "  PRINT  " + DQ$ +  "Unknown parameter and its value " + DQ$ + "; Param$; " + DQ$ + "=" + DQ$ + "; Value$"
PRINT #3, "  bOK = False"
PRINT #3, "ENDIF"
PRINT #3
PRINT #3, "IF bOK THEN "
PRINT #3, "  PRINT #7, Out$"
PRINT #3, "ENDIF"
PRINT #3 
PRINT #3, "WriteValues = bOK"
PRINT #3 
PRINT #3, "END FUNCTION ' WriteValues"

Close #1, #3 ' leave 2 open

' Now append the second function to the file containing the first function
Open Outfile1$ for input as #3
DO WHILE NOT EOF(#3)
  LINE INPUT #3, LineIn$
  PRINT #2, LineIn$
LOOP

CLOSE #2, #3

Kill OutFile1$ ' delete the temporary file

END